#pragma once

#include <mcp/config.h>
#include <mcp/transport/transport.h>

#include <memory>
#include <string>
#include <vector>
#include <functional>
#include <atomic>
#include <thread>
#include <mutex>
#include <unordered_map>

namespace mcp {
namespace transport {

/// @brief WebSocket transport configuration
struct WebSocketConfig {
    std::string host = "localhost";
    uint16_t port = 8080;
    std::string path = "/";
    std::string subprotocol = "mcp";
    std::unordered_map<std::string, std::string> headers;
    int timeout_seconds = 30;
    bool enable_compression = true;
    size_t max_message_size = 1024 * 1024; // 1MB
    int ping_interval_seconds = 30;
    int pong_timeout_seconds = 10;
};

/// @brief WebSocket transport for WebSocket-based communication
class WebSocketTransport : public Transport {
public:
    explicit WebSocketTransport(const WebSocketConfig& config = {});
    explicit WebSocketTransport(uint16_t port);
    ~WebSocketTransport() override;

    // Transport interface implementation
    bool start() override;
    void stop() override;
    bool is_connected() const override;
    bool send(const json::Value& message) override;
    std::coroutine_handle<> send_async(const json::Value& message) override;
    void set_message_handler(MessageHandler handler) override;
    void set_error_handler(ErrorHandler handler) override;
    void set_close_handler(CloseHandler handler) override;
    void set_open_handler(OpenHandler handler) override;
    std::string get_type() const override;
    json::Value get_capabilities() const override;

    /// @brief Get WebSocket URL
    /// @return WebSocket URL string
    std::string get_url() const;

    /// @brief Get WebSocket port
    /// @return WebSocket port number
    uint16_t get_port() const;

    /// @ Send ping message
    /// @return true if sent successfully, false otherwise
    bool send_ping();

    /// @brief Update configuration
    /// @param config New configuration
    void update_config(const WebSocketConfig& config);

    /// @brief Get current configuration
    /// @return Current configuration
    const WebSocketConfig& get_config() const;

private:
    struct Impl;
    std::unique_ptr<Impl> impl_;
};

/// @brief WebSocket transport factory
class WebSocketTransportFactory : public TransportFactory {
public:
    WebSocketTransportFactory() = default;

    // TransportFactory interface implementation
    std::unique_ptr<Transport> create() override;
    std::unique_ptr<Transport> create_with_config(const WebSocketConfig& config);
    std::unique_ptr<Transport> create_with_port(uint16_t port);
    std::string get_type() const override;
    std::vector<std::string> get_supported_schemes() const override;
};

} // namespace transport
} // namespace mcp